package com.chunlin.inheritance;

public class Derived extends Base{
    int a; // 与父类中成员a同名，且类型相同
    char b; // 与父类中成员b同名，但类型不同

    public Derived() {
        // super(); // 注意子类构造方法中默认会调用基类的无参构造方法：super(),
        // 用户没有写时,编译器会自动添加，而且super()必须是子类构造方法中第一条语句，
        // 并且只能出现一次
        System.out.println("Derived()");

        //在子类构造方法中，并没有写任何关于基类构造的代码，但是在构造子类对象时
        // 先执行基类的构造方法，然后执行子类的构造方法，因为：子类对象中成员是有两部分组成的，基类继承下来的以及子类新增加的部分
        // 父子父子肯定是先有父再有子，所以在构造子类对象时候,先要调用基类的构造方法，将从基类继承下来的成员构造完整
        //然后再调用子类自己的构造方法，将子类自己新增加的成员初始化完整

        //注意：
        //1. 若父类显式定义无参或者默认的构造方法，在子类构造方法第一行默认有隐含的super()调用，即调用基类构造方法
        //2. 如果父类构造方法是带有参数的，此时需要用户为子类显式定义构造方法，并在子类构造方法中选择合适的
        //父类构造方法调用，否则编译失败
        //3. 在子类构造方法中，super(...)调用父类构造时，必须是子类构造函数中第一条语句
        //4. super(...)只能在子类构造方法中出现一次，并且不能和this同时出现
    }
    public void method() {
        a = 10;
        b = 101;
        c = 102;

        //在子类方法中 或者 通过子类对象访问成员时：
        //如果访问的成员变量子类中有，优先访问自己的成员变量
        //如果访问的成员变量子类中无，则访问父类继承下来的，如果父类也没有定义，则编译报错
        //如果访问的成员变量与父类中成员变量同名，则优先访问自己的
        //成员变量访问遵循就近原则，自己有优先自己的，如果没有则向父类中找
    }

    // 与父类中methodA()构成重载
    public void methodA(int a) {
        System.out.println("Derived中的method(int)方法");
    }

    //与基类中methodB()构成重写
    @Override
    public void methodB(){
        System.out.println("Derived中的methodB()方法");
    }
    public void methodC(){
        methodA(); // 没有传参，访问父类中的methodA()
        methodA(20); // 传递int参数，访问子类中的methodA(int)
        methodB(); // 直接访问，则永远访问到的都是子类中的methodB()，基类的无法访问到

        //【说明】
        //通过子类对象访问父类与子类中不同名方法时，优先在子类中找，找到则访问，否则在父类中找，找到则访问，否则编译报错
        //通过派生类对象访问父类与子类同名方法时，如果父类和子类同名方法的参数列表不同(重载)，根据调用
        //方法适传递的参数选择合适的方法访问，如果没有则报错
    }

    public void methodD() {
        // 对于同名的成员变量，直接访问时，访问的都是子类的
        a = 100; // 等价于： this.a = 100;
        b = 101; // 等价于： this.b = 101;
        // 注意：this是当前对象的引用
        // 访问父类的成员变量时，需要借助super关键字
        // super是获取到子类对象中从基类继承下来的部分
        super.a = 200;
        super.b = 201;
        // 父类和子类中构成重载的方法，直接可以通过参数列表区分清访问父类还是子类方法
        methodA(); // 没有传参，访问父类中的methodA()
        methodA(20); // 传递int参数，访问子类中的methodA(int)
        // 如果在子类中要访问重写的基类方法，则需要借助super关键字
        methodB(); // 直接访问，则永远访问到的都是子类中的methodB()，基类的无法访问到
        super.methodB(); // 访问基类的methodB()

        //在子类方法中，如果想要明确访问父类中成员时，借助super关键字即可
        //【注意事项】
        //1. 只能在非静态方法中使用
        //2. 在子类方法中，访问父类的成员变量和方法

        //super和this
        //【相同点】
        //1. 都是Java中的关键字
        //2. 只能在类的非静态方法中使用，用来访问非静态成员方法和字段
        //3. 在构造方法中调用时，必须是构造方法中的第一条语句，并且不能同时存在

        //【不同点】
        //1. this是当前对象的引用，当前对象即调用实例方法的对象，super相当于是子类对象中从父类继承下来部分成员的引用
        //2. 在非静态成员方法中，this用来访问本类的方法和属性，super用来访问父类继承下来的方法和属性
        //3. 在构造方法中：this(...)用于调用本类构造方法，super(...)用于调用父类构造方法，两种调用不能同时在构造方法中出现
        //4. 构造方法中一定会存在super(...)的调用，用户没有写编译器也会增加，但是this(...)用户不写则没有
    }

}
